package org.anderground.app.storage;

import java.io.IOException;

import org.anderground.app.storage.ConfigData.ConfigCity;
import org.anderground.core.model.ModelData;
import org.anderground.core.storage.ModelReader;
import org.anderground.core.storage.ModelWriter;

/**
 * @author Eldar Abusalimov
 */
public abstract class PersistentStorage extends AppStorage {

	/** {@inheritDoc} */
	@Override
	protected final ModelData readModelImpl(ConfigCity city) throws IOException {
		ModelReader modelReader = getReaderForCity(city);
		if (modelReader == null) {
			throw new CreatingStorageException(
					"getReaderForCity(city) has returned null");
		}
		return modelReader.read();
	}

	/** {@inheritDoc} */
	@Override
	protected final void writeModelImpl(ModelData data, ConfigCity city)
			throws IOException {
		ModelWriter modelWriter = getWriterForCity(city);
		if (modelWriter == null) {
			throw new CreatingStorageException(
					"getWriterForCity(city) has returned null");
		}
		modelWriter.write(data);
	}

	/** {@inheritDoc} */
	@Override
	protected final ConfigData readConfigImpl(
			OnProgressCallback onProgressCallback) throws IOException {
		ConfigReader configReader = getConfigReader(onProgressCallback);
		if (configReader == null) {
			throw new CreatingStorageException(
					"getConfigReader() has returned null");
		}
		return configReader.read();
	}

	/** {@inheritDoc} */
	@Override
	protected final void writeConfigImpl(ConfigData data,
			OnProgressCallback onProgressCallback) throws IOException {
		ConfigWriter configWriter = getConfigWriter(onProgressCallback);
		if (configWriter == null) {
			throw new CreatingStorageException(
					"getConfigWriter() returned null");
		}
		configWriter.write(data);
	}

	/**
	 * Implementation should return {@link ModelReader} instance configured for
	 * reading {@link ModelData} of the specified {@link ConfigCity}.
	 * 
	 * @param city
	 *            the city definition used for creating an appropriate
	 *            ModelReader
	 * @return not null ModelReader instance (a {@link CreatingStorageException}
	 *         should be thrown instead of returning null)
	 * @throws CreatingStorageException
	 *             if something goes wrong and reader cannot be created
	 */
	protected abstract ModelReader getReaderForCity(ConfigCity city)
			throws CreatingStorageException;

	/**
	 * Implementation should return {@link ModelWriter} instance configured for
	 * writing {@link ModelData} of the specified {@link ConfigCity}.
	 * 
	 * @param city
	 *            the city definition used for creating an appropriate
	 *            ModelWriter
	 * @return not null ModelWriter instance (a {@link CreatingStorageException}
	 *         should be thrown instead of returning null)
	 * @throws CreatingStorageException
	 *             if something goes wrong and writer cannot be created
	 */
	protected abstract ModelWriter getWriterForCity(ConfigCity city)
			throws CreatingStorageException;

	/**
	 * 
	 * @param onProgressCallback
	 * @return
	 * @throws CreatingStorageException
	 */
	protected abstract ConfigReader getConfigReader(
			OnProgressCallback onProgressCallback)
			throws CreatingStorageException;

	/**
	 * 
	 * @param onProgressCallback
	 * @return
	 * @throws CreatingStorageException
	 */
	protected abstract ConfigWriter getConfigWriter(
			OnProgressCallback onProgressCallback)
			throws CreatingStorageException;

}
